package com.guoheng.hazard.sys.service.impl.hazard;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.guoheng.hazard.common.base.Result;
import com.guoheng.hazard.common.constant.CommonConstants;
import com.guoheng.hazard.common.enums.ErrorCodeEnum;
import com.guoheng.hazard.common.enums.ReviewStatusEnum;
import com.guoheng.hazard.sys.mapper.entpr.EntprBasicInfoMapper;
import com.guoheng.hazard.sys.mapper.entpr.ProductionPlaceMapper;
import com.guoheng.hazard.sys.mapper.entpr.StorageRoomMapper;
import com.guoheng.hazard.sys.mapper.entpr.StorageTankMapper;
import com.guoheng.hazard.sys.mapper.hazard.MajorHazardExamineMapper;
import com.guoheng.hazard.sys.mapper.hazard.MajorHazardInfoMapper;
import com.guoheng.hazard.sys.mapper.hazard.MajorHazardUnitMapper;
import com.guoheng.hazard.sys.model.dto.hazard.*;
import com.guoheng.hazard.sys.model.entity.entpr.EntprBasicInfo;
import com.guoheng.hazard.sys.model.entity.entpr.ProductionPlace;
import com.guoheng.hazard.sys.model.entity.entpr.StorageRoom;
import com.guoheng.hazard.sys.model.entity.entpr.StorageTank;
import com.guoheng.hazard.sys.model.entity.hazard.MajorHazardExamine;
import com.guoheng.hazard.sys.model.entity.hazard.MajorHazardInfo;
import com.guoheng.hazard.sys.model.entity.hazard.MajorHazardUnit;
import com.guoheng.hazard.sys.service.hazard.MajorHazardInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.guoheng.hazard.common.enums.PartTypeEnum.*;

/**
 * 类功能描述:　MajorHazardInfoServiceImpl
 *
 * @author fbl
 * @date 2019-33-15 15:33
 */
@Service
public class MajorHazardInfoServiceImpl implements MajorHazardInfoService {

    @Resource
    private MajorHazardInfoMapper majorHazardInfoMapper;

    @Resource
    MajorHazardUnitMapper majorHazardUnitMapper;

    @Resource
    MajorHazardExamineMapper majorHazardExamineMapper;

    @Resource
    EntprBasicInfoMapper entprBasicInfoMapper;

    @Resource
    StorageTankMapper storageTankMapper;

    @Resource
    StorageRoomMapper storageRoomMapper;

    @Resource
    ProductionPlaceMapper productionPlaceMapper;


    @Override
    public Result getHazardInfo(String majorHazardNo, Long entprId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        ArrayList<MajorHazardInfoSelectDTO> majorHazardInfoSelectDTOS = new ArrayList<>();
        // 查询重大危险源的信息
        List<MajorHazardInfo> hazardInfo = majorHazardInfoMapper.getHazardInfo(majorHazardNo, entprId);

        for (MajorHazardInfo majorHazardInfo : hazardInfo) {
            MajorHazardInfoSelectDTO majorHazardInfoSelectDTO = new MajorHazardInfoSelectDTO();
            BeanUtils.copyProperties(majorHazardInfo, majorHazardInfoSelectDTO);

            // 得到审核状态
            Integer reviewStatus = majorHazardExamineMapper.getReviewStatus(majorHazardInfo.getId());
            majorHazardInfoSelectDTO.setReviewStatus(reviewStatus);

            String majorScope = majorHazardInfo.getMajorScope();
            JSONArray majorScopeJson = JSONArray.parseArray(majorScope);
            majorHazardInfoSelectDTO.setMajorScope(majorScopeJson);
            // 得到企业名称
            Long eId = majorHazardInfo.getEntprId();
            EntprBasicInfo entprBasicInfoById = entprBasicInfoMapper.getEntprBasicInfoById(eId);
            majorHazardInfoSelectDTO.setEntprName(entprBasicInfoById.getEntprName());
            majorHazardInfoSelectDTOS.add(majorHazardInfoSelectDTO);
        }
        PageInfo<MajorHazardInfoSelectDTO> majorHazardInfoPageInfo = new PageInfo<>(majorHazardInfoSelectDTOS);
        return Result.success(majorHazardInfoPageInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateHazardInfo(MajorHazardInfoUpdateDTO majorHazardInfoUpdateDTO) {
        // 重大危险源编号不能重复
        String majorHazardNo = majorHazardInfoUpdateDTO.getMajorHazardNo();
        // 判断重大危险源编号是否修改
        MajorHazardInfo majorHazardInfo1 = majorHazardInfoMapper.selectByPrimaryKey(majorHazardInfoUpdateDTO.getId());
        // 被修改，不能重复
        if (!majorHazardNo.equals(majorHazardInfo1.getMajorHazardNo())) {
            List<MajorHazardInfo> hazardInfo = majorHazardInfoMapper.getHazardInfo(null, majorHazardInfoUpdateDTO.getEntprId());
            for (MajorHazardInfo majorHazardInfo : hazardInfo) {
                // 重大危险源编号重复
                if (majorHazardInfo.getMajorHazardNo().equals(majorHazardInfoUpdateDTO.getMajorHazardNo())) {
                    return Result.failure(ErrorCodeEnum.SYS_ERR_MAJOR_HAZARD_NO_REPEAT);
                }
            }
        }
        // 修改重大危险源信息
        MajorHazardInfo majorHazardInfo = new MajorHazardInfo();
        BeanUtils.copyProperties(majorHazardInfoUpdateDTO, majorHazardInfo);
        JSONArray majorScope = majorHazardInfoUpdateDTO.getMajorScope();
        majorHazardInfo.setMajorScope(majorScope.toJSONString());
        int update = majorHazardInfoMapper.updateByPrimaryKeySelective(majorHazardInfo);

        // 清空该重大危险源涉及的单元信息
        majorHazardUnitMapper.deleteMajorHazardInfo(majorHazardInfo.getId());

        // 重新添加单元信息
        if (majorHazardInfoUpdateDTO.getMajorHazardUnits() != null) {
            List<MajorHazardUnitUpdateDTO> majorHazardUnitUpdateDTOS = majorHazardInfoUpdateDTO.getMajorHazardUnits();
            for (MajorHazardUnitUpdateDTO majorHazardUnitUpdateDTO : majorHazardUnitUpdateDTOS) {
                MajorHazardUnit majorHazardUnit = new MajorHazardUnit();
                BeanUtils.copyProperties(majorHazardUnitUpdateDTO, majorHazardUnit);
                majorHazardUnit.setMajorHazardId(majorHazardInfo.getId());
                majorHazardUnit.setDelFlag(false);
                majorHazardUnitMapper.insert(majorHazardUnit);
            }
        }
        if (update == CommonConstants.DataBaseOperationStatus.IS_FAILURE) {
            throw new RuntimeException("修改失败");
        }
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result insertHazardInfo(MajorHazardInfoInsertDTO majorHazardInfoInsertDTO) {
        // 该企业下的重大危险源编号不能重复
        Long entprId = majorHazardInfoInsertDTO.getEntprId();
        List<MajorHazardInfo> hazardInfo = majorHazardInfoMapper.getHazardInfo(null, entprId);
        for (MajorHazardInfo majorHazardInfo : hazardInfo) {
            // 重大危险源编号重复
            if (majorHazardInfo.getMajorHazardNo().equals(majorHazardInfoInsertDTO.getMajorHazardNo())) {
                return Result.failure(ErrorCodeEnum.SYS_ERR_MAJOR_HAZARD_NO_REPEAT);
            }
        }
        // 新增重大危险源信息
        MajorHazardInfo majorHazardInfo = new MajorHazardInfo();
        BeanUtils.copyProperties(majorHazardInfoInsertDTO, majorHazardInfo);
        majorHazardInfo.setMajorScope(majorHazardInfoInsertDTO.getMajorScope().toJSONString());
        int insertSelective = majorHazardInfoMapper.insertSelective(majorHazardInfo);

        // 查询最近新增的重大危险源id
        Long lastId = majorHazardInfoMapper.getLastId();

        // 新增重大危险源涉及的单元信息
        if (majorHazardInfoInsertDTO.getMajorHazardUnits() != null) {
            List<MajorHazardUnitInsertDTO> majorHazardUnits = majorHazardInfoInsertDTO.getMajorHazardUnits();
            for (MajorHazardUnitInsertDTO majorHazardUnitDTO : majorHazardUnits) {
                MajorHazardUnit majorHazardUnit = new MajorHazardUnit();
                BeanUtils.copyProperties(majorHazardUnitDTO, majorHazardUnit);
                majorHazardUnit.setMajorHazardId(lastId);
                majorHazardUnit.setDelFlag(false);
                majorHazardUnitMapper.insert(majorHazardUnit);
            }
        }

        if (insertSelective == CommonConstants.DataBaseOperationStatus.IS_FAILURE) {
            throw new RuntimeException("修改失败");
        }
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteHazardInfo(Long id) {
        // 如果重大危险源记录审核状态不为null不可删除
        Integer reviewStatus = majorHazardExamineMapper.getReviewStatus(id);
        if (reviewStatus != null) {
            return Result.failure(ErrorCodeEnum.SYS_ERR_DEL_MAJOR_HAZARD);
        }
        // 如果重大危险源下有所属单元，不能删除
        List<MajorHazardUnit> majorHazardUnitByMajorId = majorHazardUnitMapper.getMajorHazardUnitByMajorId(id);
        if (CollectionUtil.isNotEmpty(majorHazardUnitByMajorId)) {
            return Result.failure(ErrorCodeEnum.SYS_ERR_DEL_MAJOR_HAZARD);
        }

        // 删除重大危险源信息
        MajorHazardInfo majorHazardInfo = new MajorHazardInfo();
        majorHazardInfo.setId(id);
        majorHazardInfo.setDelFlag(true);
        int deleteMajorInfo = majorHazardInfoMapper.updateByPrimaryKeySelective(majorHazardInfo);
        if (deleteMajorInfo == CommonConstants.DataBaseOperationStatus.IS_FAILURE) {
            throw new RuntimeException("删除失败");
        }
        return Result.success();
    }

    @Override
    public Result getHazardInfoDetail(Long id) {
        MajorHazardInfoSelectDTO majorHazardInfoSelectDTO = new MajorHazardInfoSelectDTO();
        // 查询重大危险源信息
        MajorHazardInfo majorHazardInfo = majorHazardInfoMapper.selectByPrimaryKey(id);
        BeanUtils.copyProperties(majorHazardInfo, majorHazardInfoSelectDTO);
        String majorScope = majorHazardInfo.getMajorScope();
        JSONArray majorScopeJson = JSONArray.parseArray(majorScope);
        majorHazardInfoSelectDTO.setMajorScope(majorScopeJson);

        Long majorHazardInfoId = majorHazardInfo.getId();
        // 查询重大危险源涉及的单元
        // 查询该重大危险源涉及的单元  重大危险源组成类型：1：储罐；2：仓库；3：生产场所
        List<MajorHazardUnit> allMajorHazardUnit = majorHazardUnitMapper.getMajorHazardUnitByMajorId(majorHazardInfoId);
        ArrayList<MajorHazardUnitDTO> majorHazardUnitDTOS = new ArrayList<>();
        for (MajorHazardUnit majorHazardUnit : allMajorHazardUnit) {
            MajorHazardUnitDTO majorHazardUnitDTO = new MajorHazardUnitDTO();
            BeanUtils.copyProperties(majorHazardUnit, majorHazardUnitDTO);

            // 置入partName
            Integer partType = majorHazardUnit.getPartType();
            Long partId = majorHazardUnit.getPartId();
            if (partType.equals(PART_TYPE_ONE.getCode())) {
                // 储罐
                StorageTank entprTankById = storageTankMapper.getEntprTankById(partId);
                majorHazardUnitDTO.setPartName(entprTankById.getTankName());
            }

            if (partType.equals(PART_TYPE_TWO.getCode())) {
                // 库房
                StorageRoom entprRoomById = storageRoomMapper.getEntprRoomById(partId);
                majorHazardUnitDTO.setPartName(entprRoomById.getRoomName());
            }

            if (partType.equals(PART_TYPE_THREE.getCode())) {
                // 生产场所
                ProductionPlace placeById = productionPlaceMapper.getPlaceById(partId);
                majorHazardUnitDTO.setPartName(placeById.getPlaceName());
            }

            majorHazardUnitDTOS.add(majorHazardUnitDTO);
        }
        majorHazardInfoSelectDTO.setMajorHazardUnits(majorHazardUnitDTOS);
        return Result.success(majorHazardInfoSelectDTO);
    }

    @Override
    public Result getHazardInfoStatistics() {
        // 获取所有重大危险源等级
        List<Integer> data = majorHazardInfoMapper.getAllMajorHazardInfo();

        // 重大危险源等级统计
        ArrayList<HazardStatisticsDTO> hazardStatisticsDTOS = new ArrayList<>();
        Map<Integer, Double> map = new HashMap<>(16);
        for (Integer type : data) {
            //定义一个计数器，用来记录重复数据的个数
            Double i = 1.0;
            if (map.get(type) != null) {
                i = map.get(type) + 1;
            }
            map.put(type, i);
        }
        for (Map.Entry<Integer, Double> integerIntegerEntry : map.entrySet()) {
            HazardStatisticsDTO hazardStatisticsDTO = new HazardStatisticsDTO();
            hazardStatisticsDTO.setMajorHazardLevel(integerIntegerEntry.getKey());
            hazardStatisticsDTO.setMajorHazardNum(integerIntegerEntry.getValue().intValue());
            // 小数精确两位
            DecimalFormat df = new DecimalFormat("#0.00");
            Double majorHazardRation = integerIntegerEntry.getValue() / data.size();
            hazardStatisticsDTO.setMajorHazardRatio(Double.valueOf(df.format(majorHazardRation)));
            hazardStatisticsDTOS.add(hazardStatisticsDTO);
        }
        // 获取所有重大危险源气体属性
        List<Integer> majorGas = majorHazardInfoMapper.getMajorGas();

        // 重大危险源气体统计
        ArrayList<HazardGasStatisticsDTO> hazardGasStatisticsDTOS = new ArrayList<>();
        Map<Integer, Double> gasMap = new HashMap<>(16);
        for (Integer type : majorGas) {
            // 定义一个计数器，用来记录重复数据的个数
            Double i = 1.0;
            if (gasMap.get(type) != null) {
                i = gasMap.get(type) + 1;
            }
            gasMap.put(type, i);
        }
        for (Map.Entry<Integer, Double> integerIntegerEntry : gasMap.entrySet()) {
            HazardGasStatisticsDTO gasStatisticsDTO = new HazardGasStatisticsDTO();
            gasStatisticsDTO.setGas(integerIntegerEntry.getKey());
            gasStatisticsDTO.setEntprNum(integerIntegerEntry.getValue().intValue());
            // 小数精确四位
            DecimalFormat df = new DecimalFormat("#0.0000");
            Double majorHazardRation = integerIntegerEntry.getValue() / data.size();
            gasStatisticsDTO.setGasRatio(Double.valueOf(df.format(majorHazardRation)));
            hazardGasStatisticsDTOS.add(gasStatisticsDTO);
        }
        HashMap<String, Object> result = new HashMap<>();
        result.put("level", hazardStatisticsDTOS);
        result.put("gas", hazardGasStatisticsDTOS);

        return Result.success(result);
    }

    @Override
    public Result getHomePageHazardInfoStatistics() {
        // 获取所有重大危险源等级和数量
        List<HomePageHazardInfoStatisticsDTO> homePageHazardStatistics = majorHazardInfoMapper.getHomePageHazardStatistics();
        ArrayList<Integer> level = new ArrayList<>();
        List<HomePageHazerdInfoEntprStatisticsDTO> entprHazards = new ArrayList<>();

        for (HomePageHazardInfoStatisticsDTO homePageHazardStatistic : homePageHazardStatistics) {
            level.add(homePageHazardStatistic.getMajorHazardLevel());
            HomePageHazerdInfoEntprStatisticsDTO homePageHazerdInfoEntprStatisticsDTO = new HomePageHazerdInfoEntprStatisticsDTO();
            // 查询该等级的企业名称
            Integer majorHazardLevel = homePageHazardStatistic.getMajorHazardLevel();
            List<String> hazardEntprName = majorHazardInfoMapper.getHazardEntprName(majorHazardLevel);
            for (String entprName : hazardEntprName) {
                // 置入企业名称
                homePageHazerdInfoEntprStatisticsDTO.setEntprName(entprName);
                // 置入该等级该企业的重大危险源名称
                List<String> majorHzardName = majorHazardInfoMapper.getMajorHzardName(entprName, majorHazardLevel);
                homePageHazerdInfoEntprStatisticsDTO.setHazardName(majorHzardName);
            }
            entprHazards.add(homePageHazerdInfoEntprStatisticsDTO);
            homePageHazardStatistic.setEntprHazards(entprHazards);
        }

        int[] levels = {1, 2, 3, 4};
        for (Integer ls : levels) {
            if(!level.contains(ls)){
                HomePageHazardInfoStatisticsDTO homePageHazardInfoStatisticsDTO = new HomePageHazardInfoStatisticsDTO();
                homePageHazardInfoStatisticsDTO.setMajorHazardLevel(ls);
                homePageHazardInfoStatisticsDTO.setMajorHazardNum(0);
                homePageHazardInfoStatisticsDTO.setEntprHazards(new ArrayList<>());
                homePageHazardStatistics.add(homePageHazardInfoStatisticsDTO);
            }
        }
        return Result.success(homePageHazardStatistics);
    }

    @Override
    public Result partUnit(Long entprId, Integer partType) {
        // 查询该企业下的组成部分id和名称,编号
        ArrayList<MajorHazardPartDTO> majorHazardPartDTOS = new ArrayList<>();
        if (partType.equals(PART_TYPE_ONE.getCode())) {
            // 储罐
            List<StorageTank> allEntprTanks = storageTankMapper.getAllEntprTanks(entprId);
            for (StorageTank allEntprTank : allEntprTanks) {
                MajorHazardPartDTO majorHazardPartDTO = new MajorHazardPartDTO();
                majorHazardPartDTO.setPartId(allEntprTank.getId());
                majorHazardPartDTO.setPartName(allEntprTank.getTankName());
                majorHazardPartDTO.setPartNo(allEntprTank.getTankNo());
                majorHazardPartDTOS.add(majorHazardPartDTO);
            }
            return Result.success(majorHazardPartDTOS);
        }

        if (partType.equals(PART_TYPE_TWO.getCode())) {
            // 库房
            List<StorageRoom> allEntprRooms = storageRoomMapper.getAllEntprRooms(entprId);
            for (StorageRoom allEntprRoom : allEntprRooms) {
                MajorHazardPartDTO majorHazardPartDTO = new MajorHazardPartDTO();
                majorHazardPartDTO.setPartId(allEntprRoom.getId());
                majorHazardPartDTO.setPartName(allEntprRoom.getRoomName());
                majorHazardPartDTO.setPartNo(allEntprRoom.getRoomNo());
                majorHazardPartDTOS.add(majorHazardPartDTO);
            }
            return Result.success(majorHazardPartDTOS);
        }

        if (partType.equals(PART_TYPE_THREE.getCode())) {
            // 生产场所
            List<ProductionPlace> allPlaces = productionPlaceMapper.getAllPlaces(entprId);
            for (ProductionPlace allPlace : allPlaces) {
                MajorHazardPartDTO majorHazardPartDTO = new MajorHazardPartDTO();
                majorHazardPartDTO.setPartId(allPlace.getId());
                majorHazardPartDTO.setPartName(allPlace.getPlaceName());
                majorHazardPartDTO.setPartNo(allPlace.getPlaceNo());
                majorHazardPartDTOS.add(majorHazardPartDTO);
            }
            return Result.success(majorHazardPartDTOS);
        }
        return null;
    }


    @Override
    public Result MajorHazardName(Long entprId) {
        // 查询重大危险源id和名称列表
        ArrayList<MajorHazardInfoNeedListDTO> majorHazardInfoNeedListDTOS = new ArrayList<>();
        List<MajorHazardInfo> hazardInfo = majorHazardInfoMapper.getHazardInfo(null, entprId);
        for (MajorHazardInfo majorHazardInfo : hazardInfo) {
            MajorHazardInfoNeedListDTO majorHazardInfoNeedListDTO = new MajorHazardInfoNeedListDTO();
            majorHazardInfoNeedListDTO.setMajorHazardId(majorHazardInfo.getId());
            majorHazardInfoNeedListDTO.setMajorHazardName(majorHazardInfo.getMajorHazardName());
            majorHazardInfoNeedListDTOS.add(majorHazardInfoNeedListDTO);
        }
        return Result.success(majorHazardInfoNeedListDTOS);
    }

    @Override
    public Result MajorHazardType(Long majorHazardId) {
        ArrayList<MajorHazardTypeDTO> majorHazardTypeDTOS = new ArrayList<>();
        // 查询重大危险源下有什么重大危险源类型
        HashSet<Integer> partTypes = new HashSet<>();
        List<MajorHazardUnit> majorHazardUnitByMajorId = majorHazardUnitMapper.getMajorHazardUnitByMajorId(majorHazardId);
        for (MajorHazardUnit majorHazardUnit : majorHazardUnitByMajorId) {
            partTypes.add(majorHazardUnit.getPartType());
        }
        for (Integer partType : partTypes) {
            MajorHazardTypeDTO majorHazardTypeDTO = new MajorHazardTypeDTO();
            // 查询该类型下有什么重大危险源
            List<MajorHazardPartName> partName = majorHazardUnitMapper.getPartName(majorHazardId, partType);
            for (MajorHazardPartName majorHazardPartName : partName) {
                // 置入重大危险源名称
                if (partType.equals(PART_TYPE_ONE.getCode())) {
                    // 储罐
                    StorageTank entprTankById = storageTankMapper.getEntprTankById(majorHazardPartName.getPartId());
                    majorHazardPartName.setPartName(entprTankById.getTankName());
                }
                if (partType.equals(PART_TYPE_TWO.getCode())) {
                    // 库房
                    StorageRoom storageRoom = storageRoomMapper.selectByPrimaryKey(majorHazardPartName.getPartId());
                    majorHazardPartName.setPartName(storageRoom.getRoomName());
                }
                if (partType.equals(PART_TYPE_THREE.getCode())) {
                    // 生产场所
                    ProductionPlace placeById = productionPlaceMapper.getPlaceById(majorHazardPartName.getPartId());
                    majorHazardPartName.setPartName(placeById.getPlaceName());
                }
            }
            majorHazardTypeDTO.setPartType(partType);
            majorHazardTypeDTO.setPartNames(partName);
            majorHazardTypeDTOS.add(majorHazardTypeDTO);
        }
        return Result.success(majorHazardTypeDTOS);
    }

    @Override
    public Result MajorHazardFiling(MajorHazardExamineDTO majorHazardId) {
        MajorHazardExamine majorHazardExamine = new MajorHazardExamine();
        BeanUtils.copyProperties(majorHazardId, majorHazardExamine);
        majorHazardExamine.setApplicationTime(new Date());
        // 待审核
        majorHazardExamine.setReviewStatus(ReviewStatusEnum.REVIEW_STATUS_1.getCode());
        int insertSelective = majorHazardExamineMapper.insertSelective(majorHazardExamine);
        if (insertSelective == CommonConstants.DataBaseOperationStatus.IS_FAILURE) {
            return Result.failure(ErrorCodeEnum.SYS_ERR_CREATE_FAILED);
        }
        return Result.success();
    }

}
